#include "stretch.h"
#include "../../layout/layout.hpp"
#include "../../select/select_cmd.hpp"
#include "../../undoRedo/undoRedo.hpp"
#include "../../utils/kutils.h"
#include "../../utils/render_polygon.h"
#include "../../utils/render_ref.h"
#include "../../utils/utils.hpp"
#include "../move/move.hpp"

namespace qbe::Stretch {
void createTempRulerRender(ecs::Query query, ecs::EventWriter<Event> event_writer, qlib::Ruler::s_ptr temp_ruler) {
  auto& temp_render_model = query.get_resource<TempRulerRenderModel>();
  temp_render_model.temp_ruler = temp_ruler;
  event_writer.send({Code::RulerCacheAdd});
}
void updateTempRulerRender(ecs::EventWriter<Event> event_writer) {
  event_writer.send({Code::RulerCacheUpdate});
}

void deleteTempRulerRender(ecs::EventWriter<Event> event_writer) {
  event_writer.send({Code::RulerCacheDelete});
}
void clear_event(ecs::Query query) {
  query.get_resource<ecs::Event<Event>>().clear();
}

bool isNaN(qlib::Vec2d pt) {
  if (std::isnan(pt.x) || std::isnan(pt.y))
    return true;
  return false;
}
void exit(ecs::Query query, state::AllModeType enter_mode) {
  auto& param = query.get_resource<StretchModel>();
  auto& state = query.get_resource<state::State>();
  auto& undoRedo = query.get_resource<undoRedoT::UndoRedoModule>();
  auto& layout_cmd = query.get_resource<layout::LayoutCmd>();
  auto& select_cmd = query.get_resource<select::SelectCmd>();
  if (state.getEditingMode() == state::EditingModeType::Stretch) {
    if (param.is_strech == true) {
      undoRedo.resetOldData();
      for (auto i : param.selects)
        layout_cmd.update(i.select_entity);
      for (auto i : param.sel_entity_all)
        layout_cmd.update(i);
      param.reset();
      auto& ecs_reg = query.get_reg();
      for (auto [e, node] : ecs_reg.view<StretchTag, vsg::ref_ptr<vsg::Switch>>().each()) {
        node->setAllChildren(false);
        node->children.clear();
      }
    }
    if (std::get<state::EditingModeType>(enter_mode) == state::EditingModeType::Undo ||
        std::get<state::EditingModeType>(enter_mode) == state::EditingModeType::Redo)
      select_cmd.clear_all();
  }
}
// 添加临时对象
void add_cache_obj(entt::registry& reg, ecs::EventWriter<move::Event> event_writer, layout::LayoutCmd& cmd, entt::entity entity, bool first) {
  if (first) {
    move::Event event;
    event.code = move::Code::Begin;
    event_writer.send(std::move(event));
  }
}

// 更新临时对象
void update_cache_obj(entt::registry& reg, ecs::EventWriter<move::Event> event_writer, layout::LayoutCmd& cmd, qlib::Vec2d translate_a,
                      qlib::Vec2d translate_b) {
  move::Event event;
  event.code = move::Code::Update;
  event.translate_a = translate_a;
  event.translate_b = translate_b;
  event_writer.send(std::move(event));
}

// 删除临时对象
void delete_cache_obj(entt::registry& reg, ecs::EventWriter<move::Event> event_writer, layout::LayoutCmd& cmd, ecs::Query query) {
  move::Event event;
  event.code = move::Code::End;
  event_writer.send(std::move(event));

  auto& sele_event_writer = query.get_event_writer<select::Event>();
  sele_event_writer.send({select::Code::SelectUpdate});
  sele_event_writer.send({select::Code::HoverUpdate});
}

void init(entt::registry& reg, ecs::Commands commands, ecs::Query query) {
  auto& state = query.get_resource<state::State>();

  for (auto [e, tran] : reg.view<render::SceneTag, vsg::ref_ptr<vsg::MatrixTransform>>().each()) {
    // 创建 Switch
    auto switchObject = vsg::Switch::create();
    tran->addChild(switchObject);
    commands.spawn(StretchTag{}, switchObject);
  }

  state.addExitCall(state::EditingModeType::Stretch, exit);
}
std::vector<SelectInfo> partSelectToStretch(ecs::Query query, std::unordered_map<entt::entity, select::SelectPartData> selects) {
  auto& cell_cmd = query.get_resource<layout::CellCmd>();
  auto& cell_reg = cell_cmd.cell->reg;
  std::vector<SelectInfo> result;
  for (auto& sel : selects) {

    SelectInfo temp_sel_info;
    temp_sel_info.select_entity = sel.first;
    auto _ptr_poly = cell_reg.try_get<qlib::Polygon::s_ptr>(temp_sel_info.select_entity);
    auto _ptr_elli = cell_reg.try_get<qlib::Ellipse::s_ptr>(temp_sel_info.select_entity);
    auto _ptr_rec = cell_reg.try_get<qlib::Rectangle::s_ptr>(temp_sel_info.select_entity);
    auto _ptr_fan = cell_reg.try_get<qlib::Fan::s_ptr>(temp_sel_info.select_entity);
    auto _ptr_line = cell_reg.try_get<qlib::Path::s_ptr>(temp_sel_info.select_entity);
    auto _ptr_ruler = cell_reg.try_get<qlib::Ruler::s_ptr>(temp_sel_info.select_entity);
    auto _ptr_section_area_3d = cell_reg.try_get<qlib::SectionArea3D::s_ptr>(temp_sel_info.select_entity);
    auto _ptr_view_area_3d = cell_reg.try_get<qlib::ViewArea3D::s_ptr>(temp_sel_info.select_entity);

    temp_sel_info.key_points = sel.second.points;

    if (!(sel.second.point_id_map.empty())) {

      if (_ptr_poly || _ptr_elli || _ptr_rec || _ptr_line || _ptr_ruler || _ptr_section_area_3d || _ptr_view_area_3d) {
        temp_sel_info.select_indexs.insert(sel.second.point_id_map.begin()->first);
      }
    }

    if (!(sel.second.edge_id_map.empty())) {
      if (_ptr_poly || _ptr_elli || _ptr_rec || _ptr_fan || _ptr_line || _ptr_ruler || _ptr_section_area_3d || _ptr_view_area_3d) {
        qlib::Vec2dArray points = temp_sel_info.key_points;
        for (auto i : sel.second.edge_id_map) {
          temp_sel_info.select_indexs.insert(i.first);
          if ((i.first + 1) >= points.size()) {
            temp_sel_info.select_indexs.insert(0);
          } else {
            temp_sel_info.select_indexs.insert(i.first + 1);
          }
        }
      }
    }
    result.push_back(temp_sel_info);
  }

  return result;
}
void preparData(ecs::Query query) {
  auto& param = query.get_resource<StretchModel>();
  auto& current_cell = query.get_resource<qlib::Cell::s_ptr>();
  auto& cell = query.get_resource<qlib::Cell::s_ptr>();
  auto& reg = cell->reg;
  // 获取移动参数
  auto event_writer = query.get_event_writer<move::Event>();
  // 获取cell和reg
  auto& layout_cmd = query.get_resource<layout::LayoutCmd>();

  param.ele_in_selected_points.clear();
  for (auto& sel : param.selects) {
    auto iter_ele = param.ele_in_selected_points.find(sel.select_entity);
    if (iter_ele == param.ele_in_selected_points.end()) {
      auto info = std::make_shared<StretchInfo>();
      info->key_points = sel.key_points;
      for (auto i : sel.select_indexs)
        info->select_indexs.insert(i);
      param.ele_in_selected_points.insert({sel.select_entity, info});
    } else {
      for (auto i : sel.select_indexs)
        iter_ele->second->select_indexs.insert(i);
    }
  }
}
void update(entt::registry& ecs_reg, ecs::Query query, ecs::Bus& bus) {
  auto& state = query.get_resource<state::State>();
  // 仅在模式执行
  if ((state.getEditingMode() == state::EditingModeType::None && state.getDrawingMode() == state::DrawingModeType::None &&
       state.getSelectMode() == state::SelectModeType::Part) ||
      state.getEditingMode() == state::EditingModeType::Stretch) {

  } else {
    return;
  }

  auto& cell_cmd = query.get_resource<layout::CellCmd>();
  auto& cell_reg = cell_cmd.cell->reg;
  auto& select_events = query.get_event_reader<select::Event>();
  auto& param = query.get_resource<StretchModel>();
  auto& layout_cmd = query.get_resource<layout::LayoutCmd>();
  auto& hand = query.get_resource<vsg::ref_ptr<input::HandleBundle>>();
  auto& select_cmd = query.get_resource<select::SelectCmd>();
  // 获取移动参数
  auto event_writer = query.get_event_writer<move::Event>();
  auto& axis = query.get_resource<axis::Axis>();
  auto& absorbModule = query.get_resource<qbe::adsorb::AdsorbModel>();

  //获取undo/red0
  auto& unredoMoudel = query.get_resource<undoRedoT::UndoRedoModule>();
  param.is_angle_lock = state.isAngleLocking();
  {
    auto res = bus.receive<UiMessage::CancelDrawing>();
    if (!res.empty()) {
      //ESC退出逻辑
      if (param.is_strech == true) {
        unredoMoudel.resetOldData();
        for (auto i : param.selects)
          layout_cmd.update(i.select_entity);
        for (auto i : param.sel_entity_all)
          layout_cmd.update(i);
        param.reset();
        state.exit();
        auto& ecs_reg = query.get_reg();
        for (auto [e, node] : ecs_reg.view<StretchTag, vsg::ref_ptr<vsg::Switch>>().each()) {
          node->setAllChildren(false);
          node->children.clear();
        }
      }
    }
  }
  //点击鼠标左键
  if (hand->mousePressed(vsg::ButtonMask::BUTTON_MASK_1)) {
    param.is_left_press = true;
  }
  if (hand->mouseReleased(1)) {
    if (param.is_strech == false) {
      param.selects.clear();
      param.sel_entity_all.clear();
      auto& selects = select_cmd.select_parts();
      param.selects = partSelectToStretch(query, selects);

      auto view = cell_reg.view<select::SelectTag>();
      view.each([&param](entt::entity e) {
        int a = 0;
        param.sel_entity_all.push_back(e);
      });
    }
    param.is_left_press = false;
  }
  //鼠标移动

  if (hand->mouse_move && param.is_left_press == true) {
    if (param.is_strech == false) {
      preparData(query);
      param.origin_x = axis.real_x;
      param.origin_y = axis.real_y;
      if (!param.selects.empty() || !param.sel_entity_all.empty()) {
        auto view = cell_reg.view<select::HoverTag>();
        view.each([&param](entt::entity e) {
          auto iter = std::find(param.sel_entity_all.begin(), param.sel_entity_all.end(), e);
          if (iter != param.sel_entity_all.end()) {
            param.is_strech = true;
          }
        });
        if (param.is_strech == false && !select_cmd.hover_parts().empty()) {
          auto iter = std::find(param.sel_entity_all.begin(), param.sel_entity_all.end(), select_cmd.hover_parts().begin()->first);
          if (iter != param.sel_entity_all.end()) {
            param.is_strech = true;
          }
        }

        if (param.is_strech == false && !select_cmd.hover_parts().empty()) {
          auto iter = param.ele_in_selected_points.find(select_cmd.hover_parts().begin()->first);
          if (iter != param.ele_in_selected_points.end()) {
            auto temp = partSelectToStretch(query, select_cmd.hover_parts());
            std::set<int> all_index;
            all_index = temp[0].select_indexs;
            int count = all_index.size();
            for (auto i : iter->second->select_indexs) {
              all_index.insert(i);
            }
            if (all_index.size() != (temp[0].select_indexs.size() + iter->second->select_indexs.size())) {
              param.is_strech = true;
            }
          }
        }
      }
    }
    if (param.is_strech == true) {
      bool first = true;
      for (auto e : param.sel_entity_all) {
        add_cache_obj(cell_reg, event_writer, layout_cmd, e, first);
        first = false;
      }
    }
  }

  if (param.is_init == false && param.is_strech == true) {
    bool is_exist_fan = false;
    state.switchMode(state::EditingModeType::Stretch);
    auto& event_writer = query.get_event_writer<select::Event>();

    for (auto [e, node] : ecs_reg.view<StretchTag, vsg::ref_ptr<vsg::Switch>>().each()) {
      node->setAllChildren(true);

      auto options = query.get_resource<vsg::ref_ptr<vsg::Options>>();
      std::shared_ptr<utils::TempRender::RenderPolygon> render_polygon =
          std::make_shared<utils::TempRender::RenderPolygon>(options, std::vector<qlib::Polygon::s_ptr>{});
      node->addChild(true, render_polygon->switchObject);
      render_polygon->setLayerType(vsg::vec4(1.0, 0.0, 1.0, 1.0), "B1");
      param.render_polygon = render_polygon;

      std::shared_ptr<utils::TempRender::RenderLine> render_line =
          std::make_shared<utils::TempRender::RenderLine>(options, std::vector<qlib::Path::s_ptr>{});
      node->addChild(true, render_line->switchObject);
      render_line->setLayerType(vsg::vec4(1.0, 0.0, 1.0, 1.0), "B1");
      param.render_line = render_line;
    }
    param.is_init = true;
    param.old_x = axis.real_x;
    param.old_y = axis.real_y;

    unredoMoudel.start(cell_cmd.cell);
    for (auto& i : param.ele_in_selected_points) {
      unredoMoudel.change(i.first);
      auto ptr = cell_reg.try_get<qlib::Fan::s_ptr>(i.first);
      if (ptr) {
        auto fan = *ptr;
        absorbModule.set_diagonal_start(fan->center);
        is_exist_fan = true;
      }
    }
    for (auto& i : param.sel_entity_all)
      unredoMoudel.change(i);
    if (is_exist_fan == false)
      absorbModule.set_diagonal_start(qlib::Vec2d(axis.real_x, axis.real_y));
  }
  if (param.is_init == false || param.is_strech == false)
    return;

  //释放鼠标左键
  if (hand->mouseReleased(1)) {
    delete_cache_obj(cell_reg, event_writer, layout_cmd, query);
    for (auto e : param.sel_entity_all) {
      qbe::utils::translate(cell_reg, e, {axis.real_x - param.origin_x, axis.real_y - param.origin_y});
    }

    for (auto& sel : param.ele_in_selected_points) {
      {
        auto _ptr = cell_reg.try_get<qlib::Polygon::s_ptr>(sel.first);
        if (_ptr) {
          auto poly = *_ptr;
          poly->points = sel.second->key_points;
        }
      }
      {
        auto _ptr = cell_reg.try_get<qlib::ViewArea3D::s_ptr>(sel.first);
        if (_ptr) {
          auto poly = *_ptr;
          poly->points = sel.second->key_points;
        }
      }
      {
        auto _ptr = cell_reg.try_get<qlib::Ellipse::s_ptr>(sel.first);
        if (_ptr) {
          auto elli = *_ptr;
          std::vector<qlib::Vec2d> points = sel.second->key_points;
          qlib::Vec2d center = (points[2] + points[0]) / 2;

          qlib::Vec2d width_height;
          width_height.x = (points[1] - points[0]).length();
          width_height.y = (points[3] - points[0]).length();

          elli->center = center;
          elli->radius = width_height / 2;
        }
      }
      {
        auto _ptr = cell_reg.try_get<qlib::Rectangle::s_ptr>(sel.first);
        if (_ptr) {
          auto rec = *_ptr;
          std::vector<qlib::Vec2d> points = sel.second->key_points;

          qlib::Vec2d width_height;
          width_height.x = (points[1] - points[0]).length();
          width_height.y = (points[3] - points[0]).length();

          qlib::Vec2d center = (points[2] + points[0]) / 2;
          rec->width = width_height.x;
          rec->height = width_height.y;
          rec->pos = center - qlib::Vec2d(width_height.x / 2.0, width_height.y / 2.0);
        }
      }

      {
        auto _ptr = cell_reg.try_get<qlib::SectionArea3D::s_ptr>(sel.first);
        if (_ptr) {
          auto rec = *_ptr;
          std::vector<qlib::Vec2d> points = sel.second->key_points;

          qlib::Vec2d width_height;
          width_height.x = (points[1] - points[0]).length();
          width_height.y = (points[3] - points[0]).length();

          qlib::Vec2d center = (points[2] + points[0]) / 2;
          rec->width = width_height.x;
          rec->height = width_height.y;
          rec->pos = center - qlib::Vec2d(width_height.x / 2.0, width_height.y / 2.0);
        }
      }

      {
        auto _ptr = cell_reg.try_get<qlib::Fan::s_ptr>(sel.first);
        if (_ptr) {
          auto fan = *_ptr;
          auto iter = param.fan_temp_fans.find(sel.first);
          if (iter == param.fan_temp_fans.end()) {
          } else {
            *fan = *(iter->second);
          }
        }
      }

      {
        auto _ptr = cell_reg.try_get<qlib::Path::s_ptr>(sel.first);
        if (_ptr) {
          auto line = *_ptr;
          std::vector<qlib::Vec2d> points = sel.second->key_points;

          line->spine.points = points;
        }
      }

      {
        auto _ptr = cell_reg.try_get<qlib::Ruler::s_ptr>(sel.first);
        if (_ptr) {
          auto ruler = *_ptr;
          std::vector<qlib::Vec2d> points = sel.second->key_points;

          ruler->start = points[0];
          ruler->end = points[1];

          if (param.temp_render_ruler) {
            auto temp_ruler_event_writer = query.get_event_writer<Event>();
            deleteTempRulerRender(temp_ruler_event_writer);
            param.temp_render_ruler = nullptr;
          }
        }
      }
    }
    for (auto i : param.selects)
      layout_cmd.update(i.select_entity);
    for (auto i : param.sel_entity_all)
      layout_cmd.update(i);

    select_cmd.clear_select_parts();
    select_cmd.clear_hover_parts();
    select::SelectCmd::PartMap part_map;
    for (auto i : param.ele_in_selected_points) {
      select::SelectPartData data;
      auto _ptr_poly = cell_reg.try_get<qlib::Polygon::s_ptr>(i.first);
      auto _ptr_elli = cell_reg.try_get<qlib::Ellipse::s_ptr>(i.first);
      auto _ptr_rec = cell_reg.try_get<qlib::Rectangle::s_ptr>(i.first);
      auto _ptr_fan = cell_reg.try_get<qlib::Fan::s_ptr>(i.first);
      auto _ptr_line = cell_reg.try_get<qlib::Path::s_ptr>(i.first);
      auto _ptr_ruler = cell_reg.try_get<qlib::Ruler::s_ptr>(i.first);

      if (_ptr_poly || _ptr_elli || _ptr_rec || _ptr_fan || _ptr_line || _ptr_ruler) {
        data.points = i.second->key_points;
        for (auto j : i.second->select_indexs) {
          data.point_id_map.insert({j, false});
        }
        part_map.insert({i.first, data});
      }
    }
    select_cmd.add_select_parts(part_map, true);

    layout_cmd.render_update();  //确定后版图更新
    unredoMoudel.end();
    param.reset();
    for (auto [e, node] : ecs_reg.view<StretchTag, vsg::ref_ptr<vsg::Switch>>().each()) {
      node->setAllChildren(false);
      node->children.clear();
    }
    state.exit();
    absorbModule.close_diagonal_start();
  }
  //鼠标移动
  if (hand->mouse_move && param.is_left_press == true) {

    double dx = axis.real_x - param.old_x;
    double dy = axis.real_y - param.old_y;
    if (stretch(query, dx, dy)) {

      update_cache_obj(cell_reg, event_writer, layout_cmd, {dx, dy}, {axis.real_x - param.origin_x, axis.real_y - param.origin_y});
      param.old_x = axis.real_x;
      param.old_y = axis.real_y;
    }
  }
}
void post(entt::registry& reg, ecs::Commands commands, ecs::Query query, ecs::Bus& bus) {}

bool stretch(ecs::Query query, double dx, double dy) {
  bool state = true;
  auto& param = query.get_resource<StretchModel>();
  auto& cell_cmd = query.get_resource<layout::CellCmd>();
  auto& cell_reg = cell_cmd.cell->reg;
  auto& axis = query.get_resource<axis::Axis>();
  auto temp_ruler_event_writer = query.get_event_writer<Event>();
  std::vector<qlib::Label::s_ptr> render_points;
  std::vector<qlib::Polygon::s_ptr> render_polys;
  std::vector<qlib::Path::s_ptr> render_lines;
  for (auto& sel : param.ele_in_selected_points) {
    {
      auto _ptr = cell_reg.try_get<qlib::Polygon::s_ptr>(sel.first);
      if (_ptr) {
        auto poly = *_ptr;
        std::vector<qlib::Vec2d> points = sel.second->key_points;
        std::set<int> indexs;
        indexs = sel.second->select_indexs;
        movePointLine(query, poly, dx, dy, points, indexs);
        sel.second->key_points = points;
        auto render_poly = std::make_shared<qlib::Polygon>();
        render_poly->points = sel.second->key_points;
        render_polys.push_back(render_poly);
      }
    }

    {
      auto _ptr = cell_reg.try_get<qlib::ViewArea3D::s_ptr>(sel.first);
      if (_ptr) {
        auto poly = *_ptr;
        std::vector<qlib::Vec2d> points = sel.second->key_points;
        std::set<int> indexs;
        indexs = sel.second->select_indexs;
        movePointLine(query, poly, dx, dy, points, indexs);
        sel.second->key_points = points;
        auto render_poly = std::make_shared<qlib::Polygon>();
        render_poly->points = sel.second->key_points;
        render_polys.push_back(render_poly);
      }
    }

    {
      auto _ptr = cell_reg.try_get<qlib::Ellipse::s_ptr>(sel.first);
      if (_ptr) {
        auto _elli = *_ptr;
        auto iter = param.elli_temp_ellis.find(sel.first);
        qlib::Ellipse::s_ptr elli;
        if (iter == param.elli_temp_ellis.end()) {
          elli = _elli->copy();
          param.elli_temp_ellis.insert({sel.first, elli});
        } else {
          elli = iter->second;
        }
        std::vector<qlib::Vec2d> points = sel.second->key_points;
        std::set<int> indexs;
        indexs = sel.second->select_indexs;
        movePointLine(query, elli, dx, dy, points, indexs);
        qbe::auxiliary::BoundingBox bb;
        bb.addPoints(points);
        qlib::Vec2d width_height = bb.max - bb.min;
        //处理拉伸时两条线重合了
        if (width_height.x <= 0 || width_height.y <= 0) {
          state = false;
        } else {
          sel.second->key_points = points;
        }

        qlib::Vec2d center = (points[2] + points[0]) / 2;

        // qlib::Vec2d width_height;
        // width_height.x = (points[1] - points[0]).length();
        // width_height.y = (points[3] - points[0]).length();

        elli->center = center;
        elli->radius = width_height / 2;

        // auto render_poly = std::make_shared<qlib::Polygon>();
        // render_poly->points = sel.second->key_points;
        render_polys.push_back(elli->to_polygon());
      }
    }
    {
      auto _ptr = cell_reg.try_get<qlib::Rectangle::s_ptr>(sel.first);
      if (_ptr) {
        auto rec = *_ptr;
        std::vector<qlib::Vec2d> points = sel.second->key_points;
        std::set<int> indexs;
        indexs = sel.second->select_indexs;
        movePointLine(query, rec, dx, dy, points, indexs);
        qbe::auxiliary::BoundingBox bb;
        bb.addPoints(points);
        qlib::Vec2d width_height = bb.max - bb.min;
        //处理拉伸时两条线重合了
        if (width_height.x <= 0 || width_height.y <= 0) {
          state = false;
        } else {
          sel.second->key_points = points;
        }

        auto render_poly = std::make_shared<qlib::Polygon>();
        render_poly->points = sel.second->key_points;
        render_polys.push_back(render_poly);
      }
    }

    {
      auto _ptr = cell_reg.try_get<qlib::SectionArea3D::s_ptr>(sel.first);
      if (_ptr) {
        auto rec = *_ptr;
        std::vector<qlib::Vec2d> points = sel.second->key_points;
        std::set<int> indexs;
        indexs = sel.second->select_indexs;
        movePointLine(query, rec, dx, dy, points, indexs);
        qbe::auxiliary::BoundingBox bb;
        bb.addPoints(points);
        qlib::Vec2d width_height = bb.max - bb.min;
        //处理拉伸时两条线重合了
        if (width_height.x <= 0 || width_height.y <= 0) {
          state = false;
        } else {
          sel.second->key_points = points;
        }

        auto render_poly = std::make_shared<qlib::Polygon>();
        render_poly->points = sel.second->key_points;
        render_polys.push_back(render_poly);
      }
    }

    {
      auto _ptr = cell_reg.try_get<qlib::Fan::s_ptr>(sel.first);
      if (_ptr) {
        auto _fan = *_ptr;
        auto iter = param.fan_temp_fans.find(sel.first);
        qlib::Fan::s_ptr fan;
        if (iter == param.fan_temp_fans.end()) {
          fan = _fan->copy();
          param.fan_temp_fans.insert({sel.first, fan});
        } else {
          fan = iter->second;
        }
        std::set<int> indexs = sel.second->select_indexs;
        double x = axis.real_x;
        double y = axis.real_y;
        double center_x = fan->center.x;
        double center_y = fan->center.y;

        //选中半径边
        if (indexs.count(0)) {
          // 当前位置与圆心连线相对x轴的角度
          double origion_Angle = atan2(param.old_y - center_y, param.old_x - center_x);
          double newAngle = atan2(y - center_y, x - center_x);
          if (origion_Angle < 0) {
            origion_Angle += 2 * M_PI;
          }
          if (newAngle < 0) {
            newAngle += 2 * M_PI;
          }
          if (indexs.count(1)) {
            // 选中的是起始半径
            double angle = fan->angle.x;
            if (fan->angle.x < 0) {
              angle += 2 * M_PI;
            }
            angle += (newAngle - origion_Angle);
            if (angle > M_PI) {
              angle -= 2 * M_PI;
            }
            fan->angle.x = angle;
          } else {
            // 选中的是终止半径
            double angle = fan->angle.y;
            if (fan->angle.y < 0) {
              angle += 2 * M_PI;
            }
            angle += (newAngle - origion_Angle);
            if (angle > M_PI) {
              angle -= 2 * M_PI;
            }
            fan->angle.y = angle;
          }
        } else {
          //选中的是圆弧
          double old_rad = (fan->center - qlib::Vec2d(param.old_x, param.old_y)).length();
          double new_rad = (fan->center - qlib::Vec2d(x, y)).length();
          fan->radius += (new_rad - old_rad);
        }
        render_polys.push_back(fan->to_polygon());
        sel.second->key_points = fan->to_polygon()->points;
      }
    }
    {
      auto _ptr = cell_reg.try_get<qlib::Path::s_ptr>(sel.first);
      if (_ptr) {
        auto line = *_ptr;
        std::vector<qlib::Vec2d> points = sel.second->key_points;
        std::set<int> indexs;
        indexs = sel.second->select_indexs;
        movePointLine(query, line, dx, dy, points, indexs);
        sel.second->key_points = points;
        auto render_line = std::make_shared<qlib::Path>();
        render_line->spine.points = sel.second->key_points;
        render_lines.push_back(render_line);
        if (line->type == qlib::PathType::WaveGuide) {
          render_line->setCenterWidth(line->getCenterWidth());
          render_line->setLineWidth(line->getLineWidth());
          render_line->setLineRadius(line->getLineRadius());
          qlib::PolygonPtrArray poly_arr;
          render_line->to_polygons(false, qlib::Tag(0, 0), poly_arr);
          render_polys.insert(render_polys.end(), poly_arr.begin(), poly_arr.end());
        }
      }
    }

    {
      auto _ptr = cell_reg.try_get<qlib::Ruler::s_ptr>(sel.first);
      if (_ptr) {
        auto ruler = *_ptr;
        if (param.temp_render_ruler == nullptr) {
          param.temp_render_ruler = ruler->copy();
          createTempRulerRender(query, temp_ruler_event_writer, param.temp_render_ruler);
        }
        std::vector<qlib::Vec2d> points = sel.second->key_points;
        std::set<int> indexs;
        indexs = sel.second->select_indexs;
        movePointLine(query, ruler, dx, dy, points, indexs);
        sel.second->key_points = points;
        auto render_line = std::make_shared<qlib::Path>();
        render_line->spine.points = sel.second->key_points;
        render_lines.push_back(render_line);
        if (param.temp_render_ruler) {
          param.temp_render_ruler->start = sel.second->key_points[0];
          param.temp_render_ruler->end = sel.second->key_points[1];
          updateTempRulerRender(temp_ruler_event_writer);
        }
      }
    }
  }
  if (param.render_line)
    param.render_line->updateData(render_lines);
  if (param.render_polygon)
    param.render_polygon->updateData(render_polys);

  return state;
}
void movePolygonLines(std::vector<std::shared_ptr<double>> slopes, int total_last_index, std::vector<int> line_indexs, int total_size,
                      std::vector<qlib::Vec2d>& points) {
  int length = line_indexs.size();
  if (length > 1) {
    int total = total_last_index;
    int head_index = line_indexs[0];
    int last_index = line_indexs[line_indexs.size() - 1];

    qlib::Vec2d head = points[head_index];
    qlib::Vec2d last = points[last_index];

    std::vector<int> before_index = auxiliary::getAroundIndex(head_index, total, 3, 1);
    std::vector<int> after_index = auxiliary::getAroundIndex(last_index, total, 3, 1);

    qlib::Vec2d a = points[before_index[0]];
    qlib::Vec2d b = points[before_index[1]];
    qlib::Vec2d c = points[after_index[0]];
    qlib::Vec2d d = points[after_index[1]];

    std::vector<std::shared_ptr<double>> line_a_head = auxiliary::slopeAndIntercept(a, head, slopes[before_index[0]]);
    std::vector<std::shared_ptr<double>> line_head_b;
    if (length == 2) {
      line_head_b = auxiliary::slopeAndIntercept(head, b, slopes[head_index]);
    } else {
      line_head_b = auxiliary::slopeAndIntercept(b, head, slopes[head_index]);
    }

    std::vector<std::shared_ptr<double>> line_c_last = auxiliary::slopeAndIntercept(c, last, slopes[after_index[0]]);
    std::vector<std::shared_ptr<double>> line_last_d = auxiliary::slopeAndIntercept(d, last, slopes[last_index]);
    if (line_a_head[0] == nullptr && line_head_b[0] == nullptr)
      return;
    if (line_c_last[0] == nullptr && line_last_d[0] == nullptr)
      return;

    qlib::Vec2d p1 = auxiliary::calculateIntersectionPoint(line_a_head, line_head_b);
    qlib::Vec2d p2 = auxiliary::calculateIntersectionPoint(line_c_last, line_last_d);

    if (isNaN(p1) || isNaN(p2)) {
      return;
    }

    points[head_index] = p1;
    points[last_index] = p2;
  } else if (length == 1) {
    int index = line_indexs[0];
    qlib::Vec2d p = points[index];

    std::vector<int> indexs = auxiliary::getAroundIndex(index, total_size - 1, 5, 2);

    qlib::Vec2d a = points[indexs[0]];
    qlib::Vec2d b = points[indexs[1]];
    qlib::Vec2d c = points[indexs[2]];
    qlib::Vec2d d = points[indexs[3]];

    std::vector<std::shared_ptr<double>> line_ab = auxiliary::slopeAndIntercept(a, b, slopes[indexs[0]]);
    std::vector<std::shared_ptr<double>> line_pb = auxiliary::slopeAndIntercept(p, b, slopes[indexs[1]]);

    std::vector<std::shared_ptr<double>> line_pc = auxiliary::slopeAndIntercept(p, c, slopes[index]);
    std::vector<std::shared_ptr<double>> line_dc = auxiliary::slopeAndIntercept(d, c, slopes[indexs[2]]);
    qlib::Vec2d p1 = auxiliary::calculateIntersectionPoint(line_ab, line_pb);
    qlib::Vec2d p2 = auxiliary::calculateIntersectionPoint(line_dc, line_pc);

    points[indexs[1]] = p1;
    points[indexs[2]] = p2;
  }
}

void moveLines(std::vector<qlib::Vec2d>& obj, std::vector<std::shared_ptr<double>> slopes, int total_last_index, std::vector<int> line_indexs) {
  int length = line_indexs.size();
  if (length == 1) {
    // 移动单个点
    int index = line_indexs[0];  // 下标

    qlib::Vec2d p = obj[index];  // 坐标
    if (index == 0) {
      // 选择首尾点
      qlib::Vec2d a = obj[1];
      auto s = slopes[0];
      std::vector<std::shared_ptr<double>> line_ap = auxiliary::slopeAndIntercept(a, p, s);
      std::shared_ptr<double> slope_line_mouse_p = nullptr;
      if (s == nullptr) {
        // bug 929 拉伸垂直线上的点
        slope_line_mouse_p = std::make_shared<double>(0);
      }
      std::vector<std::shared_ptr<double>> line_mouse_p = auxiliary::slopeAndIntercept(p, p, slope_line_mouse_p);
      qlib::Vec2d p1 = auxiliary::calculateIntersectionPoint(line_ap, line_mouse_p);
      if (isNaN(p1)) {
        return;
      }
      obj[index] = p1;
    } else if (index == total_last_index) {
      qlib::Vec2d a = obj[total_last_index - 1];
      std::shared_ptr<double> s = slopes[total_last_index - 1];
      std::vector<std::shared_ptr<double>> line_ap = auxiliary::slopeAndIntercept(a, p, s);
      std::shared_ptr<double> slope_line_mouse_p = nullptr;
      if (s == nullptr) {
        // bug 929 拉伸垂直线上的点
        slope_line_mouse_p = std::make_shared<double>(0);
      }
      std::vector<std::shared_ptr<double>> line_mouse_p = auxiliary::slopeAndIntercept(p, p, slope_line_mouse_p);
      qlib::Vec2d p1 = auxiliary::calculateIntersectionPoint(line_ap, line_mouse_p);
      if (isNaN(p1)) {
        return;
      }
      obj[index] = p1;
    } else {
      // 选择中间点 实际是移动选中点和上下一点直接线段
      int m_index = line_indexs[0];
      std::vector<int> line;
      int count = 2;
      if (m_index - 1 == 0) {
        // 第二个点
        line.push_back(m_index);
        line.push_back(m_index + 1);
      } else if (m_index + 1 == total_last_index) {
        // 最后一个点前一个点
        obj[index - 1] = obj[index];
        line.push_back(m_index - 1);
        line.push_back(m_index);
      } else {  // 中间点
        line.push_back(m_index + 1);
        line.push_back(m_index);
        line.push_back(m_index - 1);
        count = 3;
      }
      moveLines(obj, slopes, total_last_index, line);
    }
  } else {
    int total = total_last_index;
    int head_index = line_indexs[0];
    int last_index = line_indexs[line_indexs.size() - 1];  // line_indexs[end]

    // 判断收尾顺序
    qlib::Vec2d head = obj[head_index];
    qlib::Vec2d last = obj[last_index];

    std::vector<int> before_index = auxiliary::getAroundIndex(head_index, total, 3, 1);
    std::vector<int> after_index = auxiliary::getAroundIndex(last_index, total, 3, 1);

    // 计算需要移动点首尾坐标a, head, b, ...p, c, last, d 根据点求线的交点
    qlib::Vec2d a = obj[before_index[0]];
    qlib::Vec2d b = obj[before_index[1]];
    qlib::Vec2d c = obj[after_index[0]];
    qlib::Vec2d d = obj[after_index[1]];

    std::vector<std::shared_ptr<double>> line_a_head = auxiliary::slopeAndIntercept(a, head, slopes[before_index[0]]);
    std::vector<std::shared_ptr<double>> line_head_b;
    if (length == 2) {
      line_head_b = auxiliary::slopeAndIntercept(head, b, slopes[head_index]);
    } else {
      line_head_b = auxiliary::slopeAndIntercept(b, head, slopes[head_index]);
    }

    std::vector<std::shared_ptr<double>> line_c_last = auxiliary::slopeAndIntercept(c, last, slopes[after_index[0]]);
    std::vector<std::shared_ptr<double>> line_last_d = auxiliary::slopeAndIntercept(d, last, slopes[last_index]);

    qlib::Vec2d p1 = auxiliary::calculateIntersectionPoint(line_a_head, line_head_b);
    qlib::Vec2d p2 = auxiliary::calculateIntersectionPoint(line_c_last, line_last_d);
    if (isNaN(p1) || isNaN(p2)) {
      return;
    }
    obj[head_index] = p1;
    obj[last_index] = p2;
  }
}
void movePointLine(ecs::Query query, std::any ele, double dx, double dy, std::vector<qlib::Vec2d>& points, std::set<int> indexs) {
  auto& param = query.get_resource<StretchModel>();
  std::vector<std::shared_ptr<double>> slopes;
  int size = points.size() - 1;
  for (int i = 0; i < size; i++) {
    slopes.push_back(auxiliary::getSlope(points[i], points[i + 1]));
  }
  slopes.push_back(auxiliary::getSlope(points[size], points[0]));

  {
    std::vector<int> point_line_index;
    for (auto index : indexs) {
      points[index].x += dx;
      points[index].y += dy;
      point_line_index.push_back(index);
    }
    const std::type_info& stored_type = ele.type();
    if (stored_type == typeid(qlib::Ellipse::s_ptr) || stored_type == typeid(qlib::Rectangle::s_ptr) ||
        stored_type == typeid(qlib::SectionArea3D::s_ptr)) {
      // 点有顺序，处理收尾点构成的线
      if (points.size() > 2 && point_line_index.size() >= 2) {
        if (point_line_index[1] - point_line_index[0] > 1) {
          int tmp = point_line_index[0];
          point_line_index[0] = point_line_index[1];
          point_line_index[1] = tmp;
        }
      }
      movePolygonLines(slopes, size, point_line_index, points.size(), points);
    } else {
      if (param.is_angle_lock == true) {
        if (stored_type == typeid(qlib::Path::s_ptr) || stored_type == typeid(qlib::Ruler::s_ptr)) {
          auto old_points = points;
          moveLines(points, slopes, points.size() - 1, point_line_index);
          //处理线头尾点
          if (point_line_index.size() > 1) {
            auto find_0 = std::find(point_line_index.begin(), point_line_index.end(), 0);
            auto find_1 = std::find(point_line_index.begin(), point_line_index.end(), 1);
            if (find_0 != point_line_index.end() && find_1 != point_line_index.end()) {
              auto start_off = points[1] - old_points[1];
              points[0] = old_points[0] + start_off;
            }
            auto find_end_0 = std::find(point_line_index.begin(), point_line_index.end(), points.size() - 1);
            auto find_end_1 = std::find(point_line_index.begin(), point_line_index.end(), points.size() - 2);
            if (find_end_0 != point_line_index.end() && find_end_1 != point_line_index.end()) {
              auto end_off = points[points.size() - 2] - old_points[points.size() - 2];
              points[points.size() - 1] = old_points[points.size() - 1] + end_off;
            }
          }

        } else {
          // 点有顺序，处理收尾点构成的线
          if (points.size() > 2 && point_line_index.size() >= 2) {
            if (point_line_index[1] - point_line_index[0] > 1) {
              int tmp = point_line_index[0];
              point_line_index[0] = point_line_index[1];
              point_line_index[1] = tmp;
            }
          }
          movePolygonLines(slopes, size, point_line_index, points.size(), points);
        }
      }
    }
  }
}
}  // namespace qbe::Stretch